/*  

Cafechess Library: Cover basic chess programming needs, like GUI, Engine integration, 
FEN and PGN parsing.

                 \\|//
                 (o o)
--------------ooO-(_)-Ooo----------------------------------
Copyright (C) 2009  By Gregory A. Prentice Snoqualmie, WA
                    www.cafechess.org
                    cafechess@comcast.net
                      Oooo
--------------oooO----(  )---------------------------------
              (  )    (_/
               \_)

Microsoft Public License (Ms-PL)
               
Revisions:

Author        Date    Description:

*/
using System;
using System.Drawing;
using System.Windows.Forms;

using Cafechess.General;
using Cafechess.General.Handle;
using Cafechess.Imaging;

namespace Cafechess.Imaging.Draw
{
	/// <summary>
	/// Summary description for DrawOnMouseEvents.
	/// </summary>
  public abstract class DrawOnMouseEvents : Disposable, IMouseEvents, IDrawable
  {
    protected Pen coPen;

    #region Members

    private bool coDragging;
    private bool coIsLocked;
    private System.Windows.Forms.Control coControl;
    private Rectangle coRectangle;
    private String coName;
    private bool coIsEnabled;
    private Point coStartPoint;
    private Point coEndPoint;
    private Point coStartScreenPoint;
    private Point coEndScreenPoint;
    IDrawable coParent;
    #endregion Members

    #region Properties

    public Point StartPoint
    {
      get{ return coStartPoint;}
      set{ coStartPoint = value;}
    }
    public Point EndPoint
    {
      get{ return coEndPoint;}
      set{ coEndPoint = value;}
    }
    public Point StartScreenPoint
    {
      get{ return coStartScreenPoint;}
      set{ coStartScreenPoint = value;}
    }
    public Point EndScreenPoint
    {
      get{ return coEndScreenPoint;}
      set{ coEndScreenPoint = value;}
    }
    public bool IsDragging
    {
      get{return coDragging;}
      set{coDragging = value;}
    }
    public Pen Pen
    {
      set{ coPen = value;}
      get{ return coPen;}
    }
    /// <summary>
    /// Used to lock the state of this layer from any changes or movement.
    /// </summary>
    public bool IsLocked
    { 
      get{ return coIsLocked; } set{ coIsLocked = value;} 
    }
    #endregion Properties

    public DrawOnMouseEvents(System.Windows.Forms.Control aControl)
    {
      coRectangle = new Rectangle(0,0,0,0);
      coControl = aControl;
    }

    #region IMouseEvents Members

    public void DownEvent(object sender, MouseEventArgs e)
    {
      if( !IsDragging )
      {
        StartPoint = new Point(e.X,e.Y);
        EndPoint   = coStartPoint;
        StartScreenPoint = coControl.PointToScreen(StartPoint);
        EndScreenPoint   = StartScreenPoint;
        IsDragging = true;
      }
    }
    public void UpEvent(object sender, MouseEventArgs e)
    {
      if( IsDragging )
      {
        Graphics g = coControl.CreateGraphics();
        coRectangle.X = coStartPoint.X;
        coRectangle.Y = coStartPoint.Y;
        coRectangle.Height = coStartPoint.X - coEndPoint.X;
        coRectangle.Width = coStartPoint.Y - coEndPoint.Y;
        EraseMoving(g);
        DrawFinished(g);
        g.Dispose();
        IsDragging = false;
      }
    }
    public void MoveEvent(object sender, MouseEventArgs e)
    {
      if( IsDragging )
      {
        Graphics g = coControl.CreateGraphics();
        EraseMoving(g);
        EndPoint = new Point(e.X,e.Y);
        EndScreenPoint = coControl.PointToScreen(EndPoint);
        DrawMoving(g);
        g.Dispose();
      }
    }
    
    public void EnterEvent(object sender, System.EventArgs e)
    {

    }
    public void LeaveEvent(object sender, System.EventArgs  e)
    {

    }
    public void HoverEvent(object sender, System.EventArgs e)
    {
    }

    #endregion

    virtual public void EraseMoving(Graphics g)
    {
      ControlPaint.DrawReversibleLine(StartScreenPoint,EndScreenPoint, Color.Black);
    }
    virtual public void DrawMoving(Graphics g)
    {
      ControlPaint.DrawReversibleLine(StartScreenPoint,EndScreenPoint, Color.Black);
    }

//    virtual public void EraseMoving(Graphics g)
//    {
//      ControlPaint.DrawReversibleFrame(new System.Drawing.Rectangle(StartScreenPoint,
//        new Size(EndScreenPoint.X - StartScreenPoint.X,EndScreenPoint.Y - StartScreenPoint.Y)),
//        Color.Black,
//        FrameStyle.Dashed);
//
//    }
//    virtual public void DrawMoving(Graphics g)
//    {
//      ControlPaint.DrawReversibleFrame(new System.Drawing.Rectangle(StartScreenPoint,
//        new Size(EndScreenPoint.X - StartScreenPoint.X,EndScreenPoint.Y - StartScreenPoint.Y)),
//        Color.Black,
//        FrameStyle.Dashed);
//    }
    public abstract void DrawFinished(Graphics g);

    #region IDrawable Members

    public string Name
    {
      get{ return coName; }
      set{ coName = value;}
    }

    virtual public Rectangle Square
    {
      get
      {        
        return coRectangle;
      }
      set
      {
        coRectangle = value;
        StartPoint = new Point(coRectangle.X,coRectangle.Y);
        EndPoint = new Point(coRectangle.X+coRectangle.Width,coRectangle.Y+coRectangle.Height);
      }
    }
    public void Clear()
    {
    }
    public IDrawable Parent
    { get{return coParent;} set{coParent=value;}}

    public bool IsEnabled
    {
      get
      {
        // TODO:  Add DrawOnMouseEvents.IsEnabled getter implementation
        return coIsEnabled;
      }
      set
      {
        coIsEnabled = true;
      }
    }
    public bool IsRedraw
    {
      get{ return true; }
      set{ }
    }

    abstract public bool HitTest(Point point);

    public void Render(Graphics graphics)
    {
      DrawFinished(graphics);
    }

    #endregion

    #region IDisposable Members

    override protected void DisposeManaged()
    {
      if( ! IsDisposed )
      {
      }
    }
    /// <summary>
    /// Used to clean up any unmmanaged resources.
    /// </summary>
    override protected void DisposeUnmanaged()
    {
      if( ! IsDisposed )
      {
        if(coPen != null)
        {
          coPen.Dispose();
          coPen = null;
        }
      }
    }
    #endregion
  }
}
